﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.Unity.InterceptionExtension;
using System.Runtime.Caching;

namespace ASPItalia.ModelVirtualCasting.Cache.Repositories
{
    public class CacheHandler : ICallHandler
    {
        private string keyBase;
        public int timeout;
        private ObjectCache cache;
        public int Order { get; set; }

        public CacheHandler(string keyBase, int timeout, ObjectCache cache)
        {
            this.keyBase = keyBase;
            this.timeout = timeout;
            this.cache = cache;
        }

        #region ICallHandler Members

        public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
        {
            var key = buildKey(input, keyBase);

            var resultObject = cache.Get(key);
            if (resultObject != null)
            {
                return input.CreateMethodReturn(resultObject, null);
            }
            var result = getNext()(input, getNext);
            if (result.Exception == null)
            {
                cache.Add(
                    key, 
                    result.ReturnValue, 
                    new CacheItemPolicy() 
                    {
                        SlidingExpiration = TimeSpan.FromSeconds(timeout) 
                    });
            }

            return result;
        }

        private string buildKey(IMethodInvocation input, string keyBase)
        {
            long hash = 0;
            for (int i = 0; i < input.Arguments.Count; i++)
            {
                hash += Convert.ToInt64(Math.Pow(13, i)) *
                    (input.Arguments[i] == null ? 0 : input.Arguments[i].GetHashCode());
            }

            return string.Concat(keyBase, "_", hash.ToString());
        }

        #endregion
    }
}
